using System;
using System.ComponentModel;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Security.Principal;
using System.Xml.Serialization;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Utilities;
using Microsoft.SharePoint.WebPartPages;
using Microsoft.SharePoint.Administration;
using Microsoft.SharePoint.WebControls;
using System.Collections;
using System.Web;
using System.IO;
using System.Collections.Generic;
using System.Web.UI.DataVisualization.Charting;
using System.Drawing;
using System.Web.UI.WebControls.WebParts;

namespace PhilWicklund.com.PollingWebPart
{
    /// <summary>
    /// Description for PollWP.
    /// </summary>
    //[DefaultProperty("Text"),
    //ToolboxData("<{0}:PollingWebPart runat=server></{0}:PollingWebPart>"),
    //XmlRoot(Namespace = "PhilWicklund.com.PollingWebPart")]

    public class PollingWebPart : System.Web.UI.WebControls.WebParts.WebPart
    {
        int chartWidth = 250;
        [System.Web.UI.WebControls.WebParts.WebBrowsable(false),
         System.Web.UI.WebControls.WebParts.WebDisplayName("Chart Width"),
         System.Web.UI.WebControls.WebParts.WebDescription("Enter the of the chart."),
         System.Web.UI.WebControls.WebParts.Personalizable(
         System.Web.UI.WebControls.WebParts.PersonalizationScope.User),
         System.ComponentModel.Category("Chart Settings"),
         System.ComponentModel.DefaultValue(250)
        ]
        public int ChartWidth
        {
            get
            {
                return chartWidth;
            }
            set
            {
                chartWidth = value;
            }
        }

        int chartHeight = 250;
        [System.Web.UI.WebControls.WebParts.WebBrowsable(false),
         System.Web.UI.WebControls.WebParts.WebDisplayName("Chart Height"),
         System.Web.UI.WebControls.WebParts.WebDescription("Enter the of the chart."),
         System.Web.UI.WebControls.WebParts.Personalizable(
         System.Web.UI.WebControls.WebParts.PersonalizationScope.User),
         System.ComponentModel.Category("Chart Settings"),
         System.ComponentModel.DefaultValue(250)
        ]
        public int ChartHeight
        {
            get
            {
                return chartHeight;
            }
            set
            {
                chartHeight = value;
            }
        }

        private SeriesChartType chartType = SeriesChartType.Doughnut;
        [System.Web.UI.WebControls.WebParts.WebBrowsable(false),
         System.Web.UI.WebControls.WebParts.WebDisplayName("Chart Type"),
         System.Web.UI.WebControls.WebParts.WebDescription("Select which ."),
         System.Web.UI.WebControls.WebParts.Personalizable(
         System.Web.UI.WebControls.WebParts.PersonalizationScope.User),
         System.ComponentModel.Category("Chart Settings"),
         System.ComponentModel.DefaultValue(SeriesChartType.Doughnut)
        ]
        public SeriesChartType ChartType
        {
            get
            {
                return chartType;
            }
            set
            {
                chartType = value;
            }
        }

        public override EditorPartCollection CreateEditorParts()
        {
            List<EditorPart> editorParts = new List<EditorPart>(1);
            EditorPart part = new PollingEditorPart();
            part.Title = "Chart Settings";
            part.ID = this.ID + "_PollingEditorPart";
            editorParts.Add(part);
            EditorPartCollection baseparts = base.CreateEditorParts();
            return new EditorPartCollection(baseparts, editorParts);
        }

        private int cookieExpires = 14; // 14 days
        private string cookieName = "WeeklyPoll"; // Of the cookie

        private SPWeb web = null;
        private SPList list = null;

        private SPListItemCollection items = null;
        private SPListItem pollItem = null;
        private const string defaultListName = "Polls"; // List name
        private bool pollListExist = false;
        private int pollCount = 0;
        private string listName = defaultListName;
        private string pollQuestion = null;
        private string[] options = new string[6];
        private int[,] responses = new int[6, 3];
        private int optionCount = 0;
        private bool displayResults = false;          // set false to display Question and Options / true for results

        private Button ButtonSubmit = null;
        private Button ButtonCreatePollList = null;

        private LinkButton LinkShowResults = null;
        private LinkButton LinkShowQuestion = null;
        private LinkButton LinkPollList = null;

        private RadioButtonList choices = null;

        public PollingWebPart()
        {
            this.PreRender += new EventHandler(PreRenderFunc);
        }

        protected override void CreateChildControls()
        {
            try
            {
                getPollingData();
                calcResponsePercentages();

                ButtonSubmit = new Button();
                ButtonCreatePollList = new Button();

                LinkShowResults = new LinkButton();
                LinkShowQuestion = new LinkButton();
                LinkPollList = new LinkButton();

                ButtonSubmit.Text = "Submit";
                ButtonSubmit.Click += new EventHandler(ButtonSubmit_Click);
                this.Controls.Add(ButtonSubmit);

                ButtonCreatePollList.Click += new EventHandler(ButtonCreatePollList_Click);
                ButtonCreatePollList.Text = "Create Polls List";
                this.Controls.Add(ButtonCreatePollList);

                LinkShowResults.Text = "Show Results";
                LinkShowResults.Click += new EventHandler(LinkShowResults_Click);
                this.Controls.Add(LinkShowResults);

                LinkShowQuestion.Text = "Show Questions";
                LinkShowQuestion.Click += new EventHandler(LinkShowQuestion_Click);
                this.Controls.Add(LinkShowQuestion);

                LinkPollList.Text = "Polls List";
                LinkPollList.Click += new EventHandler(LinkPollList_Click);
                this.Controls.Add(LinkPollList);

                choices = new RadioButtonList();

                for (int i = 1; i <= 5; i++)
                {
                    if (options[i] != string.Empty)
                    {
                        choices.Items.Add(options[i]);
                    }
                }
                this.Controls.Add(choices);
                cookieName = cookieName += pollQuestion;
            }
            catch (Exception ex)
            {
                Context.Trace.Warn("ERROR", "CreateChildControls: " + ex.Message);
                this.Controls.Add(new LiteralControl(ex.Message));
            }
        }

        protected override void RenderContents(HtmlTextWriter output)
        {
            EnsureChildControls();

            try
            {
                if (pollListExist == false)
                {
                    output.WriteLine("<br />");
                    output.WriteLine("The Polls list does not exist for this WebPart. <br />");
                    output.WriteLine("Create the Polls list with the button below and then add a question and options to the Polls list.");
                    output.WriteLine("<br /><br />");
                    ButtonCreatePollList.RenderControl(output);
                }
                else
                {
                    if (pollCount > 0)
                    {
                        if (displayResults == false && HttpContext.Current.Request.Cookies[cookieName] == null)
                        {
                            // Display the polling question
                            output.WriteLine("<table width=\"100%\" >");
                            output.WriteLine("<tr>");
                            output.WriteLine("<td colspan=\"2\" >");
                            output.WriteLine(pollQuestion);
                            choices.RenderControl(output);
                            output.WriteLine("</td>");
                            output.WriteLine("</tr>");

                            // Display the submit and show results button 
                            output.WriteLine("<tr>");
                            output.WriteLine("<td align=\"left\" >");
                            output.WriteLine("<div id=\"pollSubmitButton\">");
                            ButtonSubmit.RenderControl(output);
                            output.WriteLine("</div>");
                            output.WriteLine("</td>");
                            output.WriteLine("<td align=\"right\" >");
                            LinkShowResults.RenderControl(output);
                            output.WriteLine("</td>");
                            output.WriteLine("</tr>");
                            output.WriteLine("</table>");
                        }
                        else
                        {
                            // Display results of poll
                            output.WriteLine("<table width=\"100%\" >");
                            output.WriteLine("<tr>");
                            output.WriteLine("<td>Poll Results");
                            output.WriteLine("<table class=\"poll-results-table\" >");
                            output.WriteLine("<tr>");
                            output.WriteLine("<td colspan=\"2\" class=\"poll-question\" >");
                            output.WriteLine(pollQuestion);
                            output.WriteLine("</td>");
                            output.WriteLine("</tr>");

                            output.WriteLine("<tr>");
                            output.WriteLine("<td colspan=\"2\" class=\"poll-question\" >");

                            Chart Chart1 = new Chart();
                            Chart1.Page = this.Page;
                            Chart1.ImageType = ChartImageType.Png;
                            Chart1.ImageStorageMode = ImageStorageMode.UseHttpHandler;
                            Chart1.RenderType = RenderType.ImageTag;
                            Chart1.Palette = ChartColorPalette.None;
                            Color[] colors = { Color.RoyalBlue, Color.OrangeRed, Color.LightGreen, Color.Orange, Color.LightBlue };
                            Chart1.PaletteCustomColors = colors;

                            int[] yValues = new int[0];
                            string[] xValues = new string[0];
                            // Populate series data

                            if (options[3] != string.Empty)
                            {
                                if (options[4] != string.Empty)
                                {
                                    if (options[5] != string.Empty)
                                    {
                                        int[] y = { responses[1, 0], responses[2, 0], responses[3, 0], responses[4, 0], responses[5, 0] };
                                        yValues = y;
                                        string[] x = { responses[1, 1].ToString() + "%", responses[2, 1].ToString() + "%", responses[3, 1].ToString() + "%", responses[4, 1].ToString() + "%", responses[5, 1].ToString() + "%" };
                                        xValues = x;
                                    }
                                    else
                                    {
                                        int[] y = { responses[1, 0], responses[2, 0], responses[3, 0], responses[4, 0] };
                                        yValues = y;
                                        string[] x = { responses[1, 1].ToString() + "%", responses[2, 1].ToString() + "%", responses[3, 1].ToString() + "%", responses[4, 1].ToString() + "%" };
                                        xValues = x;
                                    }
                                }
                                else
                                {
                                    int[] y = { responses[1, 0], responses[2, 0], responses[3, 0] };
                                    yValues = y;
                                    string[] x = { responses[1, 1].ToString() + "%", responses[2, 1].ToString() + "%", responses[3, 1].ToString() + "%" };
                                    xValues = x;
                                }
                            }
                            else
                            {
                                int[] y = { responses[1, 0], responses[2, 0] };
                                yValues = y;
                                string[] x = { responses[1, 1].ToString() + "%", responses[2, 1].ToString() + "%" };
                                xValues = x;
                            }

                            Series series = new Series("Default");
                            Chart1.Series.Add(series);
                            Chart1.Series["Default"].Points.DataBindXY(xValues, yValues);

                            Chart1.Series["Default"].ChartType = ChartType;
                            Chart1.Width = ChartWidth;
                            Chart1.Height = ChartHeight;

                            Chart1.Series["Default"]["PieLabelStyle"] = "Inside";

                            ChartArea area = new ChartArea("ChartArea1");
                            Chart1.ChartAreas.Add(area);
                            Chart1.ChartAreas["ChartArea1"].Area3DStyle.Enable3D = true;

                            Legend legend = new Legend();
                            Chart1.Legends.Add(legend);
                            Chart1.Legends[0].Enabled = false;

                            Chart1.RenderControl(output);
                            output.WriteLine("</td>");
                            output.WriteLine("</tr>");

                            if (options[1] != string.Empty)
                            {
                                output.WriteLine("<tr><td align=\"left\"><table width='10px' height='10px' bgcolor='" + colors[0].ToKnownColor().ToString() + "'><tr><td></td></tr></table></td>");
                                output.WriteLine("<td align=\"left\" width=\"100%\">" + options[1] + " (" + responses[1, 0] + ")</td></tr>");
                            }
                            if (options[2] != string.Empty)
                            {
                                output.WriteLine("<tr><td align=\"left\"><table width='10px' height='10px' bgcolor='" + colors[1].ToKnownColor().ToString() + "'><tr><td></td></tr></table></td>");
                                output.WriteLine("<td align=\"left\" width=\"100%\">" + options[2] + " (" + responses[2, 0] + ")</td></tr>");
                            }
                            if (options[3] != string.Empty)
                            {
                                output.WriteLine("<tr><td align=\"left\"><table width='10px' height='10px' bgcolor='" + colors[2].ToKnownColor().ToString() + "'><tr><td></td></tr></table></td>");
                                output.WriteLine("<td align=\"left\" width=\"100%\">" + options[3] + " (" + responses[3, 0] + ")</td></tr>");
                            }
                            if (options[4] != string.Empty)
                            {
                                output.WriteLine("<tr><td align=\"left\"><table width='10px' height='10px' bgcolor='" + colors[3].ToKnownColor().ToString() + "'><tr><td></td></tr></table></td>");
                                output.WriteLine("<td align=\"left\" width=\"100%\">" + options[4] + " (" + responses[4, 0] + ")</td></tr>");
                            }
                            if (options[5] != string.Empty)
                            {
                                output.WriteLine("<tr><td align=\"left\"><table width='10px' height='10px' bgcolor='" + colors[4].ToKnownColor().ToString() + "'><tr><td></td></tr></table></td>");
                                output.WriteLine("<td align=\"left\" width=\"100%\">" + options[5] + " (" + responses[5, 0] + ")</td></tr>");
                            }

                            output.WriteLine("<tr class=\"poll-results-data\" >");
                            output.WriteLine("<td colspan=\"2\">Total Number of Responses: " + responses[0, 0].ToString() + "</td>");
                            output.WriteLine("</tr>");
                            output.WriteLine("</table></td></tr></table>");
                        }
                    }
                    else
                    {
                        // No items in the Poll list
                        output.WriteLine("<br />No Polling items exist. ");
                        output.WriteLine("Add a polling question and options to the Polls list.");
                        LinkPollList.RenderControl(output);
                    }
                } // Poll List exists
            }
            catch (Exception ex)
            {
                output.WriteLine(ex.Message);
            }
        } // end render WebPart

        // Read polling question, options and results 
        private void getPollingData()
        {
            //Instantiate context Web and specified list
            web = SPControl.GetContextWeb(Context);

            foreach (SPList list in web.Lists)
            {
                if (list.Title != listName)
                    continue;
                pollListExist = true;
                break;
            }

            if (pollListExist == true)
            {
                //Get the collection of items on the list and last item
                list = web.Lists[listName];
                items = list.Items;
                pollCount = list.ItemCount;

                if (pollCount != 0)
                {
                    pollItem = list.Items[list.ItemCount - 1];

                    // Get the Question
                    pollQuestion = pollItem["Question"].ToString();

                    // Loop thru options to load array
                    for (int i = 1; i <= 5; i++)
                    {
                        if (pollItem["Option" + i] != null)
                        {
                            options[i] = pollItem["Option" + i].ToString();
                        }
                        else
                        {
                            options[i] = "";
                        }
                        responses[i, 0] = Convert.ToInt32(pollItem["Response" + i]);
                    }
                }
            }
        }

        // Load response array with calculated percentages
        private void calcResponsePercentages()
        {
            responses[0, 0] = 0;
            // 0,0 row,col array element is total of all responses
            for (int i = 1; i < 6; i++)
            {
                if (options[i] != string.Empty)
                {
                    optionCount++;
                    responses[0, 0] = responses[0, 0] + responses[i, 0];
                }
            }

            // Calculate % and store in column 1 and remaining % in column 2
            for (int i = 1; i < 6; i++)
            {
                if (options[i] != string.Empty)
                {
                    optionCount++;
                    responses[i, 1] = (int)((float)responses[i, 0] / (float)responses[0, 0] * 100F);
                    responses[i, 2] = 100 - responses[i, 1];
                }
            }
        }

        // Add option selected by user to results
        private void ButtonSubmit_Click(object sender, System.EventArgs e)
        {
            try
            {
                HttpCookie cookie = new HttpCookie(cookieName);
                cookie.Value = "true";
                cookie.Expires = DateTime.Now.AddDays(cookieExpires);
                HttpContext.Current.Response.Cookies.Add(cookie);

                updatePollList();
            }
            catch (Exception ex)
            {
                string error = ex.ToString();
                error += "2";
                //output.WriteLine("ERROR RenderWebpart: " + ex.Message);
            }
        }

        public void updatePollList()
        {
            // Get index of option selected
            int selectedIndex = choices.SelectedIndex;

            // Test if user selected an option	
            if (selectedIndex > -1)
            {
                // Loop thru options to match option selected
                string optionQuestion = choices.SelectedItem.Text;
                for (int i = 1; i <= 5; i++)
                {
                    if (options[i] == optionQuestion)
                    {
                        // Increment response array and Poll list on SharePoint
                        responses[i, 0] = responses[i, 0] + 1;

                        Utilities.WSSUtilities.UdateListItemWithAppPoolIdentity(web.Site.ID, web.ID, "Polls", pollItem.ID, "Response" + i, responses[i, 0].ToString());
                    }
                }
                // Turn off selection and recalculate percentages
                choices.SelectedIndex = -1;
                calcResponsePercentages();
            }

            displayResults = true;        // Set display results flag on

        }

        // Create Polls list and add to Sharepoint database
        private void ButtonCreatePollList_Click(object sender, System.EventArgs e)
        {
            web.AllowUnsafeUpdates = true;
            web.Lists.Add("Polls", "Polling items", SPListTemplateType.GenericList);
            SPList pollsList = web.Lists["Polls"];
            SPView view = pollsList.Views["All Items"];
            SPViewFieldCollection viewFields = view.ViewFields;

            SPField field = pollsList.Fields["Title"];
            field.Title = "Question";
            field.Update();

            string fieldID = pollsList.Fields.Add("Option1", SPFieldType.Note, true);
            field = (SPField)pollsList.Fields.GetField(fieldID);
            viewFields.Add(field);
            view.Update();

            fieldID = pollsList.Fields.Add("Option2", SPFieldType.Note, true);
            field = (SPField)pollsList.Fields.GetField(fieldID);
            viewFields.Add(field);
            view.Update();

            fieldID = pollsList.Fields.Add("Option3", SPFieldType.Note, false);
            field = (SPField)pollsList.Fields.GetField(fieldID);
            viewFields.Add(field);
            view.Update();

            fieldID = pollsList.Fields.Add("Option4", SPFieldType.Note, false);
            field = (SPField)pollsList.Fields.GetField(fieldID);
            viewFields.Add(field);
            view.Update();

            fieldID = pollsList.Fields.Add("Option5", SPFieldType.Note, false);
            field = (SPField)pollsList.Fields.GetField(fieldID);
            viewFields.Add(field);
            view.Update();

            fieldID = pollsList.Fields.Add("Response1", SPFieldType.Number, true);
            field = (SPField)pollsList.Fields.GetField(fieldID);
            viewFields.Add(field);
            view.Update();
            field.DefaultValue = "0";
            field.Update();

            fieldID = pollsList.Fields.Add("Response2", SPFieldType.Number, true);
            field = (SPField)pollsList.Fields.GetField(fieldID);
            viewFields.Add(field);
            view.Update();
            field.DefaultValue = "0";
            field.Update();

            fieldID = pollsList.Fields.Add("Response3", SPFieldType.Number, true);
            field = (SPField)pollsList.Fields.GetField(fieldID);
            viewFields.Add(field);
            view.Update();
            field.DefaultValue = "0";
            field.Update();

            fieldID = pollsList.Fields.Add("Response4", SPFieldType.Number, true);
            field = (SPField)pollsList.Fields.GetField(fieldID);
            viewFields.Add(field);
            view.Update();
            field.DefaultValue = "0";
            field.Update();

            fieldID = pollsList.Fields.Add("Response5", SPFieldType.Number, true);
            field = (SPField)pollsList.Fields.GetField(fieldID);
            viewFields.Add(field);
            view.Update();
            field.DefaultValue = "0";
            field.Update();

            Page.Response.Redirect(web.Url + "/Lists/Polls");
        }

        // Add CSS style sheet to page for display of graph
        private void PreRenderFunc(object sender, System.EventArgs e)
        {
            // Add a CSS style sheet for displaying the poll questions and results
            string scriptKey = "pollCSS";
            string resourcePath = SPWebPartManager.GetClassResourcePath(
              Microsoft.SharePoint.SPContext.Current.Web,
              this.GetType()) + "/PollWebPartStyles.css";

            string scriptToRegister = "<Link  REL=\"stylesheet\" type=\"text/css\" href=\"" + resourcePath + "\" >";

            if (!Page.ClientScript.IsClientScriptBlockRegistered(scriptKey))
                Page.ClientScript.RegisterClientScriptBlock(this.GetType(), scriptKey, scriptToRegister);
        }

        private void LinkShowResults_Click(object sender, EventArgs e)
        {
            calcResponsePercentages();
            displayResults = true;        // Set display results flag off
        }

        private void LinkShowQuestion_Click(object sender, EventArgs e)
        {
            calcResponsePercentages();
            displayResults = false;       // Set display results flag off
        }

        private void LinkPollList_Click(object sender, EventArgs e)
        {
            Page.Response.Redirect(web.Url + "/Lists/Polls");
        }
    }
}
